/* the following heavily leveraged from linux/arch/ia64/hp/sim/fw-emu.c */
-#define NUM_EFI_SYS_TABLES 6
-# define NUM_MEM_DESCS 5
+/* Set IP and GR1 of not yet initialized vcpu. */
+static void
+set_os_boot_rendez (struct domain *d, unsigned long pc, unsigned long gr1)
+{
+ struct vcpu *v;
+ int i;
+ printf ("set_os_boot_rendez: %lx %lx\n", pc, gr1);
+ for (i = 1; i < MAX_VIRT_CPUS; i++) {
+ v = d->vcpu[i];
+ if (v != NULL
+ && !test_bit(_VCPUF_initialised, &v->vcpu_flags)) {
+ struct pt_regs *regs = vcpu_regs (v);
+ regs->cr_iip = pc;
+ regs->r1 = gr1;
+ }
+ }
+}
struct sal_ret_values
sal_emulator (long index, unsigned long in1, unsigned long in2,
printf("NON-PRIV DOMAIN CALLED SAL_PCI_CONFIG_WRITE\n");
break;
case SAL_SET_VECTORS:
- printf("*** CALLED SAL_SET_VECTORS. IGNORED...\n");
+ if (in1 == SAL_VECTOR_OS_BOOT_RENDEZ) {
+ if (in4 != 0 || in5 != 0 || in6 != 0 || in7 != 0) {
+ /* Sanity check: cs_length1 must be 0,
+ second vector is reserved. */
+ status = -2;
+ }
+ else
+ set_os_boot_rendez (current->domain, in2, in3);
+ }
+ else
+ printf("*** CALLED SAL_SET_VECTORS %lu. IGNORED...\n",
+ in1);
break;
case SAL_GET_STATE_INFO:
/* No more info. */
return;
}
+#define NUM_EFI_SYS_TABLES 6
+#define NUM_MEM_DESCS 5
+
static struct ia64_boot_param *
dom_fw_init (struct domain *d, const char *args, int arglen, char *fw_mem, int fw_mem_size)
{
efi_runtime_services_t *efi_runtime;
efi_config_table_t *efi_tables;
struct ia64_sal_systab *sal_systab;
- efi_memory_desc_t *efi_memmap, *md;
struct ia64_sal_desc_entry_point *sal_ed;
+ struct ia64_sal_desc_ap_wakeup *sal_wakeup;
+ efi_memory_desc_t *efi_memmap, *md;
struct ia64_boot_param *bp;
unsigned long *pfn;
unsigned char checksum = 0;
efi_tables = (void *) cp; cp += NUM_EFI_SYS_TABLES * sizeof(*efi_tables);
sal_systab = (void *) cp; cp += sizeof(*sal_systab);
sal_ed = (void *) cp; cp += sizeof(*sal_ed);
+ sal_wakeup = (void *) cp; cp += sizeof(*sal_wakeup);
efi_memmap = (void *) cp; cp += NUM_MEM_DESCS*sizeof(*efi_memmap);
bp = (void *) cp; cp += sizeof(*bp);
pfn = (void *) cp; cp += NFUNCPTRS * 2 * sizeof(pfn);
sal_systab->size = sizeof(*sal_systab);
sal_systab->sal_rev_minor = 1;
sal_systab->sal_rev_major = 0;
- sal_systab->entry_count = 1;
+ sal_systab->entry_count = 2;
strcpy((char *)sal_systab->oem_id, "Xen/ia64");
strcpy((char *)sal_systab->product_id, "Xen/ia64");
dom_fw_hypercall_patch (d, sal_ed->sal_proc, FW_HYPERCALL_SAL_CALL, 1);
sal_ed->gp = 0; // will be ignored
+ /* Fill an AP wakeup descriptor. */
+ sal_wakeup->type = SAL_DESC_AP_WAKEUP;
+ sal_wakeup->mechanism = IA64_SAL_AP_EXTERNAL_INT;
+ sal_wakeup->vector = XEN_SAL_BOOT_RENDEZ_VEC;
+
for (cp = (char *) sal_systab; cp < (char *) efi_memmap; ++cp)
checksum += *cp;
}
+static void
+fw_hypercall_ipi (struct pt_regs *regs)
+{
+ int cpu = regs->r14;
+ int vector = regs->r15;
+ struct vcpu *targ;
+
+ if (0 && vector == 254)
+ printf ("send_ipi from %d to %d vector=%d\n",
+ current->vcpu_id, cpu, vector);
+
+ if (cpu > MAX_VIRT_CPUS)
+ return;
+
+ targ = current->domain->vcpu[cpu];
+ if (targ == NULL)
+ return;
+
+ if (vector == XEN_SAL_BOOT_RENDEZ_VEC
+ && !test_bit(_VCPUF_initialised, &targ->vcpu_flags)) {
+ struct pt_regs *targ_regs = vcpu_regs (targ);
+ struct vcpu_guest_context c;
+
+ printf ("arch_boot_vcpu: %p %p\n",
+ (void *)targ_regs->cr_iip,
+ (void *)targ_regs->r1);
+ memset (&c, 0, sizeof (c));
+ /* Copy regs. */
+ c.regs.cr_iip = targ_regs->cr_iip;
+ c.regs.r1 = targ_regs->r1;
+
+ /* Copy from vcpu 0. */
+ c.vcpu.evtchn_vector =
+ current->domain->vcpu[0]->vcpu_info->arch.evtchn_vector;
+ if (arch_set_info_guest (targ, &c) != 0) {
+ printf ("arch_boot_vcpu: failure\n");
+ return;
+ }
+ if (test_and_clear_bit(_VCPUF_down,
+ &targ->vcpu_flags)) {
+ vcpu_wake(targ);
+ printf ("arch_boot_vcpu: vcpu %d awaken %016lx!\n",
+ targ->vcpu_id, targ_regs->cr_iip);
+ }
+ else
+ printf ("arch_boot_vcpu: huu, already awaken!");
+ }
+ else {
+ int running = test_bit(_VCPUF_running,
+ &targ->vcpu_flags);
+
+ vcpu_pend_interrupt(targ, vector);
+ vcpu_unblock(targ);
+ if (running)
+ smp_send_event_check_cpu(targ->processor);
+ }
+ return;
+}
+
static int
fw_hypercall (struct pt_regs *regs)
{
// FIXME: need fixes in efi.h from 2.6.9
regs->r8 = EFI_UNSUPPORTED;
break;
+ case FW_HYPERCALL_IPI:
+ fw_hypercall_ipi (regs);
+ break;
default:
printf("unknown ia64 fw hypercall %lx\n", regs->r2);
regs->r8 = do_ni_hypercall();
*/
#define FW_HYPERCALL_FIRST_ARCH 0x300UL
+#define FW_HYPERCALL_IPI 0x380UL
+
/* Xen/ia64 user hypercalls. Only used for debugging. */
#define FW_HYPERCALL_FIRST_USER 0xff00UL
+/* Interrupt vector used for os boot rendez vous. */
+#define XEN_SAL_BOOT_RENDEZ_VEC 0xF3
+
extern struct ia64_pal_retval xen_pal_emulator(UINT64, u64, u64, u64);
extern struct sal_ret_values sal_emulator (long index, unsigned long in1, unsigned long in2, unsigned long in3, unsigned long in4, unsigned long in5, unsigned long in6, unsigned long in7);
extern struct ia64_pal_retval pal_emulator_static (unsigned long);